package com.tebiecloud.base.server.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.tebiecloud.base.client.constants.ResourceType;
import com.tebiecloud.base.client.model.AuthorityResource;
import com.tebiecloud.base.client.model.entity.*;
import com.tebiecloud.base.server.mapper.*;
import com.tebiecloud.base.server.service.*;
import com.tebiecloud.common.mybatis.base.service.impl.BaseServiceImpl;
import com.tebiecloud.common.security.SecurityConstants;
import com.tebiecloud.common.security.SecurityAuthority;
import com.tebiecloud.common.utils.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Map;

/**
 * 系统权限-菜单权限、操作权限、API权限 服务实现类
 * @author tebie
 * @date 2019-08-01
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class BaseAuthorityServiceImpl extends BaseServiceImpl<BaseAuthorityMapper, BaseAuthority> implements BaseAuthorityService {

    @Autowired
    private BaseAuthorityMapper baseAuthorityMapper;
    @Autowired
    private BaseAuthorityRoleMapper baseAuthorityRoleMapper;
    @Autowired
    private BaseAuthorityUserMapper baseAuthorityUserMapper;
    @Autowired
    private BaseAuthorityAppMapper baseAuthorityAppMapper;
    @Autowired
    private BaseAuthorityActionMapper baseAuthorityActionMapper;

    @Autowired
    private BaseMenuService baseMenuService;
    @Autowired
    private BaseActionService baseActionService;
    @Autowired
    private BaseApiService baseApiService;
    @Autowired
    private BaseRoleService baseRoleService;
//    @Autowired
//    private BaseUserService baseUserService;
//    @Autowired
//    private BaseAppService baseAppService;
//    @Autowired
//    private RedisTokenStore redisTokenStore;

    /**
     * 获取访问权限列表
     * @return
     */
    @Override
    public List<AuthorityResource> getAuthorityResourceList() {
        List<AuthorityResource> list = Lists.newArrayList();
        // 已授权资源权限
        List<AuthorityResource> resourceList = baseAuthorityMapper.selectAllAuthorityResource();
        if (resourceList != null) {
            list.addAll(resourceList);
        }
        return list;
    }

    /**
     * 获取所有可用权限
     * @param type = -1 查询全部  type = 1 获取菜单和操作 type = 2 获取API
     * @return
     */
    @Override
    public List<SecurityAuthority> getSecurityAuthorityListByType(int type) {
        return baseAuthorityMapper.selectAuthority(1, type);
    }

    /**
     * 获取应用已授权权限
     * @param appId
     * @return
     */
    @Override
    public List<SecurityAuthority> getSecurityAuthorityListByAppId(String appId) {
        List<SecurityAuthority> list = baseAuthorityAppMapper.selectSecurityAuthority(appId);
        if (list == null) {
            list = Lists.newArrayList();
        }
        return list;
    }

    /**
     * 获取用户已授权权限
     * @param userId
     * @param root 超级管理员
     * @return
     */
    @Override
    public List<SecurityAuthority> getSecurityAuthorityList(Long userId, Boolean root) {
        if (root) {
            // 超级管理员返回所有
            return getSecurityAuthorityListByType(1);
        }
        List<SecurityAuthority> authorities = Lists.newArrayList();
        List<BaseRole> rolesList = baseRoleService.getBaseRoleList(userId);
        if (rolesList != null) {
            for (BaseRole role : rolesList) {
                // 加入角色已授权
                List<SecurityAuthority> roleGrantedAuthority = baseAuthorityRoleMapper.selectAuthorityByRoleId(role.getRoleId());
                if (roleGrantedAuthority != null && roleGrantedAuthority.size() > 0) {
                    authorities.addAll(roleGrantedAuthority);
                }
            }
        }
        // 加入用户特殊授权
        List<SecurityAuthority> userGrantedAuthority = baseAuthorityUserMapper.selectAuthorityByUserId(userId);
        if (userGrantedAuthority != null && userGrantedAuthority.size() > 0) {
            authorities.addAll(userGrantedAuthority);
        }
        // 权限去重
        HashSet h = new HashSet(authorities);
        authorities.clear();
        authorities.addAll(h);

        return authorities;
    }

    /**
     * 获取权限
     * @param resourceId
     * @param resourceType
     * @return
     */
    @Override
    public BaseAuthority getAuthority(Long resourceId, ResourceType resourceType) {
        if (resourceId == null || resourceType == null) {
            return null;
        }
        QueryWrapper<BaseAuthority> queryWrapper = buildQueryWrapper(resourceId, resourceType);
        return baseAuthorityMapper.selectOne(queryWrapper);
    }

    /**
     * 保存或修改权限
     * @param resourceId
     * @param resourceType
     * @return 权限Id
     */
    @Override
    public BaseAuthority saveOrUpdateAuthority(Long resourceId, ResourceType resourceType) {
        BaseAuthority baseAuthority = getAuthority(resourceId, resourceType);
        String authority = null;
        if (baseAuthority == null) {
            baseAuthority = new BaseAuthority();
        }

        if (ResourceType.menu.equals(resourceType)) {
            BaseMenu menu = baseMenuService.getById(resourceId);
            authority = SecurityConstants.AUTHORITY_PREFIX_MENU + menu.getMenuCode();
            baseAuthority.setMenuId(resourceId);
            baseAuthority.setStatus(menu.getStatus());
        } else if (ResourceType.action.equals(resourceType)) {
            BaseAction operation = baseActionService.getById(resourceId);
            authority = SecurityConstants.AUTHORITY_PREFIX_ACTION + operation.getActionCode();
            baseAuthority.setActionId(resourceId);
            baseAuthority.setStatus(operation.getStatus());
        } else if (ResourceType.api.equals(resourceType)) {
            BaseApi api = baseApiService.getById(resourceId);
            authority = SecurityConstants.AUTHORITY_PREFIX_API + api.getApiCode();
            baseAuthority.setApiId(resourceId);
            baseAuthority.setStatus(api.getStatus());
        }

        if (authority == null) {
            return null;
        }
        // 设置权限标识
        baseAuthority.setAuthority(authority);
        if (baseAuthority.getAuthorityId() == null) {
            // 新增权限
            baseAuthorityMapper.insert(baseAuthority);
        } else {
            // 修改权限
            baseAuthorityMapper.updateById(baseAuthority);
        }
        return baseAuthority;
    }

    /**
     * 清理无效数据
     * @param serviceId
     * @param codes
     */
    @Override
    public void clearInvalidApi(String serviceId, Collection<String> codes) {
        if (StringUtils.isBlank(serviceId)) {
            return;
        }
        List<String> invalidApiIds = baseApiService.listObjs(new QueryWrapper<BaseApi>().select("api_id").eq("service_id", serviceId).notIn(codes!=null&&!codes.isEmpty(),"api_code", codes), e -> e.toString());
        if (invalidApiIds != null) {
            // 防止删除默认api
            invalidApiIds.remove("1");
            invalidApiIds.remove("2");
            // 获取无效的权限
            if (invalidApiIds.isEmpty()) {
                return;
            }
            List<String> invalidAuthorityIds = listObjs(new QueryWrapper<BaseAuthority>().select("authority_id").in("api_id", invalidApiIds), e -> e.toString());
            if (invalidAuthorityIds != null && !invalidAuthorityIds.isEmpty()) {
                // 移除关联数据
                baseAuthorityAppMapper.delete(new QueryWrapper<BaseAuthorityApp>().in("authority_id", invalidAuthorityIds));
                baseAuthorityActionMapper.delete(new QueryWrapper<BaseAuthorityAction>().in("authority_id", invalidAuthorityIds));
                baseAuthorityRoleMapper.delete(new QueryWrapper<BaseAuthorityRole>().in("authority_id", invalidAuthorityIds));
                baseAuthorityUserMapper.delete(new QueryWrapper<BaseAuthorityUser>().in("authority_id", invalidAuthorityIds));
                // 移除权限数据
                this.removeByIds(invalidAuthorityIds);
                // 移除接口资源
                baseApiService.removeByIds(invalidApiIds);
            }
        }
    }

    /**
     * 构建权限对象
     * @param resourceId
     * @param resourceType
     * @return
     */
    private QueryWrapper<BaseAuthority> buildQueryWrapper(Long resourceId, ResourceType resourceType) {
        QueryWrapper<BaseAuthority> queryWrapper = new QueryWrapper();
        if (ResourceType.menu.equals(resourceType)) {
            queryWrapper.lambda().eq(BaseAuthority::getMenuId, resourceId);
        }
        if (ResourceType.action.equals(resourceType)) {
            queryWrapper.lambda().eq(BaseAuthority::getActionId, resourceId);
        }
        if (ResourceType.api.equals(resourceType)) {
            queryWrapper.lambda().eq(BaseAuthority::getApiId, resourceId);
        }
        return queryWrapper;
    }

}
